package com.hcryan.djm.utils;

import com.hcryan.djm.config.MinioConfig;
import io.minio.*;
import io.minio.errors.ErrorResponseException;
import io.minio.http.Method;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.UUID;

/**
 * @author ryanwdj
 * @since 2025/5/3
 */
@Component
public class MinioUtil {

    private final MinioClient minioClient;
    private final String bucketName;

    @Autowired
    public MinioUtil(MinioConfig minioConfig) throws Exception {
        this.minioClient = MinioClient.builder()
                .endpoint(minioConfig.getEndpoint())
                .credentials(minioConfig.getAccessKey(), minioConfig.getSecretKey())
                .build();
        this.bucketName = minioConfig.getBucketName();
        createBucketIfNotExists();
    }

    /**
     * 创建存储桶（如果不存在）
     */
    private void createBucketIfNotExists() throws Exception {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder()
                .bucket(bucketName)
                .build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        }
    }

    /**
     * 上传文件（自动生成路径）
     */
    public String uploadFile(MultipartFile file) throws Exception {
        String objectName = generateObjectName(file.getOriginalFilename());
        return uploadFile(file, objectName);
    }

    /**
     * 上传文件（自定义路径）
     */
    public String uploadFile(MultipartFile file, String objectName) throws Exception {
        try (InputStream inputStream = file.getInputStream()) {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
            return objectName;
        }
    }

    /**
     * 获取临时访问链接（默认7天有效期）
     */
    public String getFileUrl(String objectName) throws Exception {
        return getFileUrl(objectName, 7 * 24 * 3600);
    }

    /**
     * 获取临时访问链接（自定义有效期）
     */
    public String getFileUrl(String objectName, int expirySeconds) throws Exception {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                .method(Method.GET)
                .bucket(bucketName)
                .object(objectName)
                .expiry(expirySeconds)
                .build());
    }

    /**
     * 删除文件
     */
    public void deleteFile(String objectName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build());
    }

    /**
     * 检查文件是否存在
     */
    public boolean fileExists(String objectName) throws Exception {
        try {
            minioClient.statObject(StatObjectArgs.builder()
                    .bucket(bucketName)
                    .object(objectName)
                    .build());
            return true;
        } catch (ErrorResponseException e) {
            if (e.response().code() == 404) {
                return false;
            }
            throw e;
        }
    }

    /**
     * 下载文件
     *
     * @param objectName 存储路径
     * @return 文件流
     */
    public InputStream download(String objectName) {
        try {
            return minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketName)
                            .object(objectName)
                            .build());
        } catch (Exception e) {
            throw new RuntimeException("文件下载失败", e);
        }
    }

    /**
     * 生成唯一对象名称（日期目录+UUID）
     */
    private String generateObjectName(String originalFilename) {
        String extension = "";
        if (originalFilename != null && originalFilename.contains(".")) {
            extension = originalFilename.substring(originalFilename.lastIndexOf("."));
        }
        return String.format("%s/%s%s",
                java.time.LocalDate.now(),
                UUID.randomUUID(),
                extension);
    }
}